package com.woohua.thread.completefeature;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/***
 * @title OrTask
 * @description: 使用一个任务先返回的结果
 * @author woo hua
 * @version 1.0.0
 * @create 2023/3/21 10:27
 **/
public class OrTask {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 13. applyToEither 使用A，B两个异步任务优先返回的结果, 并有返回值
        CompletableFuture<String> future13 = CompletableFuture.supplyAsync(() -> {
            sleep(200); // 虽热这个任务优先执行，但是执行时间比下面的任务长，所以最后会使用下面的返回结果
            System.out.println("13.1 TaskA be called"); // 用于证明拿到B的结果后，A还会继续执行，并不会终止
            return "13.2 TaskA return value";
        }).applyToEither(CompletableFuture.supplyAsync(() -> {
            sleep(100);
            System.out.println("13.3 TaskA be called");
            return "13.4 TaskB return value";
        }), (returnVal) -> returnVal);
        System.out.println("13.5 get: " + future13.get());
        sleep(300);

        // 14. acceptEither 使用A，B两个异步任务优先返回的结果， 无返回值
        CompletableFuture.supplyAsync(() -> {
            sleep(200); // 虽热这个任务优先执行，但是执行时间比下面的任务长，所以最后会使用下面的返回结果
            System.out.println("14.1 TaskA be called"); // 用于证明拿到B的结果后，A还会继续执行，并不会终止
            return "14.2 TaskA return value";
        }).acceptEither(CompletableFuture.supplyAsync(() -> {
            sleep(100);
            System.out.println("14.3 TaskB be called");
            return "14.4 TaskB return value";
        }), (returnVal) -> {
            System.out.println("14.5 get: " + returnVal);
        });
        sleep(300);

        // 15. runAfterEither A，B任意一个执行完成后就执行C，C不关心前面任务的返回值
        CompletableFuture.supplyAsync(() -> {
            sleep(200); // 虽热这个任务优先执行，但是执行时间比下面的任务长，所以最后会使用下面的返回结果
            System.out.println("15.1 TaskA be called"); // 用于证明拿到B的结果后，A还会继续执行，并不会终止
            return "15.2 TaskA return value";
        }).runAfterEither(CompletableFuture.supplyAsync(() -> {
            sleep(100);
            System.out.println("15.3 TaskB be called");
            return "15.4 TaskB return value";
        }), () -> {
            System.out.println("15.5 TaskC be called");
        });
        sleep(300);
    }

    private static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
